﻿namespace Refract.UI.Docking
{
    using System.Windows;
    using System.Windows.Controls;

    using Artefact.Animation;

    using Refract.Event;
    using Refract.Navigation;

    #region Enumerations

    public enum DockFrameState
    {
        Normal,
        Hover,
        Undockable
    }

    #endregion Enumerations

    [TemplatePart(Name = "Container", Type = typeof(Panel))]
    [TemplatePart(Name = "Frame", Type = typeof(FrameworkElement))]
    [TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
    [TemplateVisualState(Name = "Hover", GroupName = "CommonStates")]
    [TemplateVisualState(Name = "Undockable", GroupName = "CommonStates")]
    public class DockFrame : Control, IDock
    {
        #region Constructors

        public DockFrame()
        {
            DefaultStyleKey = typeof(DockFrame);
        }

        #endregion Constructors

        #region Properties

        public string RegionName
        {
            get; set;
        }

        public DockFrameState State
        {
            get; set;
        }

        private Panel Container
        {
            get; set;
        }

        private FrameworkElement Frame
        {
            get; set;
        }

        #endregion Properties

        #region Methods

        public bool CanDock(FrameworkElement element, Point position)
        {
            return Container.Children.Count == 0;
        }

        public bool Dock(FrameworkElement element, Point position, SimpleCallback dockCompletedCallback = null)
        {
            var previousContainer = element.Parent as Panel;
            if (previousContainer != null)
            {
                previousContainer.Children.Remove(element);
                Canvas.SetTop(element, Canvas.GetTop(element) - Canvas.GetTop(this) - Container.Margin.Top - BorderThickness.Top);
                Canvas.SetLeft(element, Canvas.GetLeft(element) - Canvas.GetLeft(this) - Container.Margin.Left - BorderThickness.Left);
            }

            Container.Children.Add(element);

            IDockable dockable = element as IDockable;
            if (dockable != null) { dockable.Maximize(); }

            return false;
        }

        public bool Hover(FrameworkElement element, Point position, SimpleCallback dockCompletedCallback = null)
        {
            State = DockFrameState.Hover;
            GotoState();
            return false;
        }

        public override void OnApplyTemplate()
        {
            Container = (Panel)GetTemplateChild("Container");
            Frame = (FrameworkElement)GetTemplateChild("Frame");

            base.OnApplyTemplate();
            Region.SetRegion(RegionName, this);
            GotoState();
        }

        public bool Undock(FrameworkElement element, Point position, SimpleCallback dockCompletedCallback = null)
        {
            Container.Children.Remove(element);
            var frameContainer = Parent as Panel;
            if (frameContainer != null)
            {
                frameContainer.Children.Add(element);

            }

            IDockable dockable = element as IDockable;
            if(dockable != null) { dockable.Restore();}

            return false;
        }

        public bool Unhover(FrameworkElement element, Point position, SimpleCallback dockCompletedCallback = null)
        {
            State = DockFrameState.Normal;
            GotoState();
            return false;
        }

        private void GotoState(bool useTransitions = true)
        {
            VisualStateManager.GoToState(this, State.ToString(), useTransitions);
        }

        #endregion Methods
    }
}